package com.upbos.upm.module;

import com.upbos.cache.SingleCacheManager;
import com.upbos.upm.common.UpmConfiguration;
import com.upbos.upm.entity.App;
import com.upbos.upm.entity.Module;
import com.upbos.upm.entity.ModuleRes;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <b>Application name：</b> ModuleService.java <br>
 * <b>Application describing： 功能模块service</b> <br>
 * <b>Copyright：</b> Copyright &copy; 2018 upbos.com 版权所有。<br>
 * <b>Company：</b> upbos.com <br>
 * <b>Date：</b> 2019年1月9日 10:28 <br>
 * <b>author：</b> <a href="mailto:wangjz@miyzh.com"> wangjz </a> <br>
 * <b>version：</b>V4.2.0 <br>
 */
@Service
public class ModuleService {
    @Resource
    private ModuleDao moduleDao;

    @Resource
    private SingleCacheManager singleCacheManager;

    @Resource
    private UpmConfiguration configuration;
    /**
     * 获取应用列表
     *
     * @return 应用列表
     */
    public List<App> listApp() {
        return moduleDao.listApp();
    }

    /**
     * 获取功能模块的资源列表
     *
     * @param moduleId 功能模块Id
     * @return 资源列表
     */
    public List<ModuleRes> listModuleRes(String moduleId) {
        return moduleDao.listModuleRes(moduleId);
    }

    /**
     * 获取功能模块树
     *
     * @return 功能模块树
     */
    public List<Module> listMenuTree() {
        // 获取全部功能模块列表
        List<Module> lst = moduleDao.listAllModule();
        return buildModuleTree(lst);
    }

    /**
     * 构建功能模块树
     *
     * @param moduleList 功能模块列表
     * @return 功能模块树
     */
    public List<Module> buildModuleTree(List<Module> moduleList) {
        // 构建根节点
        Module root = new Module("0", "功能菜单树", "home", "0");
        renderTree(root, moduleList);

        List<Module> result = new ArrayList<>();
        result.add(root);
        return result;
    }

    private void renderTree(Module parentModule, List<Module> tree) {
        // 递归构建每个功能模块的下级功能模块列表
        tree.stream().filter(module -> parentModule.getId().equals(module.getParentId())).forEach(module -> {
            List<Module> children = parentModule.getChildren();
            if (children == null) {
                children = new ArrayList<>();
                parentModule.setChildren(children);
            }
            children.add(module);
            renderTree(module, tree);
        });
    }

    /**
     * 保存功能模块
     *
     * @param module 功能模块
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveModule(Module module) {
        if (module.getId() == null) {
            // 找出节点最大序号
            Module maxNode = moduleDao.getMaxIdxModule(module.getParentId());
            module.setIdx(maxNode == null ? 1 : maxNode.getIdx() + 1);
            moduleDao.insertModule(module);
        } else {
            moduleDao.updateModule(module);
        }

        // 先删除该功能模块的资源
        moduleDao.deleteModuleRes(module.getCascade());
        // 然后插入该功能模块的资源列表
        moduleDao.insertModuleRes(module.getId(), module.getResList());
        // 因为用户登录时会缓存所有功能模块，所有要删除功能模块的缓存数据
        singleCacheManager.getCache(configuration.getCacheName()).remove(configuration.getCacheModuleKey());
    }

    /**
     * 删除功能模块，并且删除该功能模块的下级节点，以及对应的资源
     *
     * @param id 功能模块Id
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteModule(String id) {
        // 功能模块的层级
        String cascade = moduleDao.getModuleCascade(id);
        // 1. 先删除该功能模块对应的资源
        moduleDao.deleteModuleRes(cascade);
        // 2. 然后删除功能模块
        moduleDao.deleteModule(cascade);
        // 3. 删除功能模块的缓存数据
        singleCacheManager.getCache(configuration.getCacheName()).remove(configuration.getCacheModuleKey());
    }

    /**
     * 移动功能模块的上下级关系
     *
     * @param srcId  被移动的功能模块Id
     * @param destId 目标功能模块Id
     * @param type
     */
    public void sort(String srcId, String destId, Integer type) {
        // 被移动的节点
        Module srcModule = moduleDao.getModule(srcId);
        // 目标节点
        Module destModule = moduleDao.getModule(destId);

        if (type == 0) {
            // 如果拖拽节点被拖到目标节点下，则找到目标节点排序号最大的子节点，将移动节点序号加1，插到目标节点下
            Module maxChildNode = moduleDao.getMaxIdxModule(destId);
            srcModule.setIdx(maxChildNode == null ? 1 : maxChildNode.getIdx() + 1);
            srcModule.setParentId(destId);
            moduleDao.updateModule(srcModule);
            String newCascade;
            if ("0".equals(destModule.getId())) {
                newCascade = srcModule.getId();
            } else {
                newCascade = destModule.getCascade() + "." + srcModule.getId();
            }

            // 更新功能模块相关层级
            moduleDao.updateCascade(srcModule.getCascade(), newCascade);
            // 删除缓存
            singleCacheManager.getCache(configuration.getCacheName()).remove(configuration.getCacheModuleKey());
            return;
        }

        Module parentModule = moduleDao.getModule(destModule.getParentId());
        List<Module> brotherModule = moduleDao.listModuleByParentId(destModule.getParentId());

        List<Module> sortModuleList = brotherModule.stream().filter(module -> !module.getId().equals(srcId)).collect(Collectors.toList());
        int pos = 0;
        for (Module currentModule : sortModuleList) {
            pos++;
            if (currentModule.getId().equals(destId)) {
                break;
            }
        }
        srcModule.setParentId(destModule.getParentId());
        sortModuleList.add(type == 1 ? pos - 1 : pos, srcModule);

        for (int i = 0; i < sortModuleList.size(); i++) {
            Module m = sortModuleList.get(i);
            m.setIdx(i + 1);
            moduleDao.updateModule(m);
        }

        // 更新功能模块相关层级
        String newCascade;
        if ("0".equals(parentModule.getId())) {
            newCascade = srcModule.getId();
        } else {
            newCascade = parentModule.getCascade() + "." + srcModule.getId();
        }

        moduleDao.updateCascade(srcModule.getCascade(), newCascade);
        // 删除缓存
        singleCacheManager.getCache(configuration.getCacheName()).remove(configuration.getCacheModuleKey());
    }
}
